home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Applications / Publishing / ImagePortfolio / Source / ImagePortfolio.m < prev    next >
Text File  |  1994-04-01  |  14KB  |  468 lines

  1. // -------------------------------------------------------------------------------------
  2. // ImagePortfolio.m - Visual TIFF/EPS file manager
  3. // Author: Martin D. Flynn
  4. // You may freely copy, distribute and reuse the code in this example.
  5. // NeXT disclaims any warranty of any kind, expressed or implied, as to its
  6. // fitness for any particular use.
  7. // -------------------------------------------------------------------------------------
  8.  
  9. #import <libc.h>
  10. #import <stdlib.h>
  11. #import <stdio.h>
  12. #import <string.h>
  13. #import <mach/mach.h>
  14. #import <objc/List.h>
  15. #import <objc/objc-runtime.h>
  16. #import <objc/NXBundle.h>
  17. #import <defaults/defaults.h>
  18. #import <dpsclient/wraps.h>
  19. #import    <appkit/Window.h>
  20. #import <appkit/Panel.h>
  21. #import <appkit/OpenPanel.h>
  22. #import <appkit/Text.h>
  23. #import <appkit/TextField.h>
  24. #import <appkit/Button.h>
  25. #import <appkit/Matrix.h>
  26. #import <appkit/Font.h>
  27. #import <appkit/ScrollView.h>
  28. #import <appkit/Speaker.h>
  29. #import <appkit/Listener.h>
  30. #import    <appkit/Menu.h>
  31. #import    <appkit/MenuCell.h>
  32. #import <appkit/graphics.h>
  33. #import <appkit/publicWraps.h>
  34. #import <appkit/NXImage.h>
  35. #import <appkit/NXBitmapImageRep.h>
  36. #import <appkit/NXEPSImageRep.h>
  37. #import "GifImageRep.h"
  38. #import "ImagePortfolio.h"
  39. #import "Portfolio.h"
  40. #import "PaletteCell.h"        // for adding support image types
  41. #import "PaletteMatrix.h"
  42.  
  43. // -------------------------------------------------------------------------------------
  44. // version number
  45. #define    versionNUMBER        "1.30"
  46.  
  47. // -------------------------------------------------------------------------------------
  48. // This is done for the purpose of allowing to setDelegate on the appIcon window
  49. // [DelegateWindow poseAs:[Window class]] must be issued in +new(Application) 
  50. @interface DelegateWindow:Window @end
  51. @implementation DelegateWindow
  52. - setDelegate:sender
  53. {
  54.     if ((wFlags.style != NX_TOKENSTYLE) && (wFlags.style != NX_MINIWORLDSTYLE)) {
  55.         [super setDelegate:sender];
  56.     } else {
  57.         int saveStyle = wFlags.style;
  58.         wFlags.style = NX_PLAINSTYLE;
  59.         [super setDelegate:sender];
  60.         wFlags.style = saveStyle;
  61.     }
  62.     return self;
  63. }
  64. @end
  65.  
  66. // -------------------------------------------------------------------------------------
  67. @implementation ImagePortfolio
  68.  
  69. // -------------------------------------------------------------------------------------
  70. // menu/button actions
  71.  
  72. /* make and show new image Palette */
  73. - newImagePalette:sender
  74. {
  75.     return [[Portfolio alloc] initFromFile:(char*)nil];
  76. }
  77.  
  78. /* open Palette file */
  79. - open:sender
  80. {
  81.     id        pOpen;
  82.     char    fName[MAXPATHLEN+1], *dir, **files, *fTypes[] = { docEXTENSION, 0 };
  83.  
  84.     /* build/display open panel */
  85.     pOpen = [OpenPanel new];
  86.     [pOpen setTitle:"Open Image Portfolio"];
  87.     [pOpen setPrompt:"File:"];
  88.     [pOpen setRequiredFileType:fTypes[0]];
  89.     [pOpen allowMultipleFiles:YES];
  90.     [pOpen setDirectory:[NXApp lastPath]];
  91.     if (![pOpen runModalForTypes:fTypes]) return self;
  92.  
  93.     /* open the list of selected files */
  94.     if (!(files = (char**)[pOpen filenames])) return self;
  95.     if (dir=(char*)[pOpen directory]) { chdir(dir); [self setLastPath:dir]; }
  96.     while (*files) {
  97.         sprintf(fName, "%s/%s", dir, *files++);
  98.         [[Portfolio alloc] initFromFile:fName];
  99.     }
  100.  
  101.     return self;
  102. }
  103.  
  104. /* arrange windows in front */
  105. - arrangeInFront:sender
  106. {
  107.     return self;
  108. }
  109.  
  110. /* show info panel */
  111. - showInfo:sender
  112. {
  113.     return [infoPanel makeKeyAndOrderFront:sender];
  114. }
  115.  
  116. /* show help panel */
  117. - showHelp:sender
  118. {
  119.     return [helpPanel makeKeyAndOrderFront:sender];
  120. }
  121.  
  122. /* show preferences panel (to be called by PaletteMatrix only!) */
  123. - showPreferences:sender
  124. {
  125.     id    winDel = [Portfolio activePortfolio];
  126.     int    rows, cols;
  127.   
  128.     /* exit if not proper portfolio type (must match sender) */
  129.     if (!winDel || ![winDel isKindOf:[Portfolio class]]) return self;
  130.   
  131.     /* set screen fields */
  132.     [fontName setStringValue:[[winDel font] name]];
  133.     [fontSize setFloatValue:[[winDel font] pointSize]];
  134.     [prefCellWidth  setFloatValue:[winDel cellSize]->width ];
  135.     [prefCellHeight setFloatValue:[winDel cellSize]->height];
  136.     [winDel getDisplayedRows:&rows cols:&cols];
  137.     [prefCellRows setIntValue:rows];
  138.     [prefCellColumns setIntValue:cols];
  139.   
  140.     /* show window */
  141.     [prefPanel makeKeyAndOrderFront:sender];
  142.     [NXApp runModalFor:prefPanel];
  143.   
  144.     return self;
  145. }
  146.  
  147. /* cancel preferences */
  148. - cancelPreferences:sender
  149. {
  150.     [NXApp stopModal:0];
  151.     [prefPanel orderOut:sender];
  152.     return self;
  153. }
  154.  
  155. /* save preference to defaults table */
  156. - saveDefaults:sender
  157. {
  158.     id    winDel = [Portfolio activePortfolio];
  159.     if (winDel && [winDel isKindOf:[Portfolio class]]) [winDel saveDefaults:sender];
  160.     return self;
  161. }
  162.  
  163. /* print key window */
  164. - printKeyWindow:sender
  165. {
  166.     return (keyWindow)? [keyWindow smartPrintPSCode:sender] : (id)nil;
  167. }
  168.  
  169. // -------------------------------------------------------------------------------------
  170. // return application constants
  171.  
  172. /* set last default saved/openned file path */
  173. - setLastPath:(char*)path
  174. {
  175.     return [self setLastPathNoCopy:NXCopyStringBuffer(path)];
  176. }
  177.  
  178. /* set last default saved/openned file path */
  179. - setLastPathNoCopy:(char*)path
  180. {
  181.     if (lastPath) free(lastPath);
  182.     lastPath = path;
  183.     return self;
  184. }
  185.  
  186. /* return last saved/openned path */
  187. - (const char*)lastPath
  188. {
  189.     return (lastPath)? lastPath : NXHomeDirectory();
  190. }
  191.  
  192. // -------------------------------------------------------------------------------------
  193. // inline event dispatcher
  194. // - When this method is interleaved with other methods, such as loading a large image
  195. //   directory, this allows continued interaction with the user.
  196. - dispatchEvents
  197. {
  198.     NXEvent    *e;
  199.     while (e=[NXApp getNextEvent:NX_MOUSEDOWNMASK waitFor:0.0 threshold:NX_BASETHRESHOLD])
  200.         [NXApp sendEvent:e];
  201.     return self;
  202. }
  203.   
  204. // -------------------------------------------------------------------------------------
  205. // menu cell update handler methods
  206.  
  207. - _setMenuCellsUpdateAction:menuId
  208. {
  209.     id    cellList = [[menuId itemList] cellList];
  210.     int    i = [cellList count];
  211.     while(i) {
  212.         id cell = [cellList objectAt:--i];
  213.         SEL    updAct, cSel = [cell action];
  214.         if ([cell hasSubmenu]) { [self _setMenuCellsUpdateAction:[cell target]]; continue; }
  215.         if ([cell target]) continue;
  216.         updAct = @selector(_ucKeyWindow:);    // default updateAction
  217.         if (cSel==@selector(cut:)               ) updAct=@selector(_ucCutCopyDelete:); else
  218.         if (cSel==@selector(copy:)                ) updAct=@selector(_ucCutCopyDelete:); else
  219.         if (cSel==@selector(delete:)            ) updAct=@selector(_ucCutCopyDelete:); else
  220.         if (cSel==@selector(undelete:)            ) updAct=@selector(_ucUndelete:);      else
  221.         if (cSel==@selector(paste:)                ) updAct=@selector(_ucResponder:);     else
  222.         if (cSel==@selector(save:)                ) updAct=@selector(_ucSelectable:);    else
  223.         if (cSel==@selector(saveAs:)            ) updAct=@selector(_ucSelectable:);    else
  224.         if (cSel==@selector(print:)                ) updAct=@selector(_ucSelectable:);    else
  225.         if (cSel==@selector(selectAll:)            ) updAct=@selector(_ucSelectable:);    else
  226.         if (cSel==@selector(sortByCellTitle:)   ) updAct=@selector(_ucSelectable:);    else
  227.         if (cSel==@selector(showPreferences:)   ) updAct=@selector(_ucMainWindow:);    else
  228.         if (cSel==@selector(performClose:)        ) updAct=@selector(_ucKeyWindow:);     else
  229.         if (cSel==@selector(performMiniaturize:)) updAct=@selector(_ucKeyWindow:);     else
  230.         if (cSel==@selector(printKeyWindow:)    ) updAct=@selector(_ucKeyWindow:);
  231.         [cell setUpdateAction:updAct forMenu:menuId];
  232.         [menuId setAutoupdate:YES];
  233.     }
  234.     return self;
  235. }
  236.  
  237. /* return menuCell responder */
  238. - _cellResponder:cellId
  239. {
  240.     id    respId = (keyWindow)? [keyWindow firstResponder] : (id)nil;
  241.     return (respId && [respId respondsTo:[cellId action]])? respId : (id)nil;
  242. }
  243.  
  244. /* return menuCell enabling flag */
  245. - (BOOL)_cellEnabler:cellId :(SEL)meth
  246. {
  247.     id    respId = [self _cellResponder:cellId];
  248.     [cellId setEnabled:((respId&&[respId respondsTo:meth]&&[respId perform:meth])?YES:NO)];
  249.     return YES;
  250. }
  251.  
  252. /* print/save/saveAs/selectAll: cells selectable */
  253. - (BOOL)_ucSelectable:cellId
  254. {
  255.     return [self _cellEnabler:cellId :@selector(anySelectableCells)];
  256. }
  257.  
  258. /* cut/copy/delete */
  259. - (BOOL)_ucCutCopyDelete:cellId
  260. {
  261.     return [self _cellEnabler:cellId :@selector(selectedCell)];
  262. }
  263.  
  264. /* undelete */
  265. - (BOOL)_ucUndelete:cellId
  266. {
  267.     return [self _cellEnabler:cellId :@selector(undeletable)];
  268. }
  269.  
  270. /* keyWindow menu cell update method */
  271. - (BOOL)_ucKeyWindow:cellId
  272. {
  273.     [cellId setEnabled:(keyWindow?YES:NO)];
  274.     return YES;
  275. }
  276.  
  277. /* mainWindow menu cell update method */
  278. - (BOOL)_ucMainWindow:cellId
  279. {
  280.     [cellId setEnabled:(mainWindow?YES:NO)];
  281.     return YES;
  282. }
  283.  
  284. /* paste */
  285. - (BOOL)_ucResponder:cellId
  286. {
  287.     [cellId setEnabled:([self _cellResponder:cellId]?YES:NO)];
  288.     return YES;
  289. }
  290.  
  291. // -------------------------------------------------------------------------------------
  292. // application delegate
  293.  
  294. /* Application instantiation */
  295. + new
  296. {
  297.     [DelegateWindow poseAs:[Window class]];
  298.     return [super new];
  299. }
  300.  
  301. /* application initialization */
  302. - appDidInit:sender
  303. {
  304.     NXAtom    pbsTypes[1];
  305.  
  306.     /* clear vars */
  307.     lastPath = (char*)nil;
  308.     
  309.     
  310.     /* set the first responder update actions */
  311.     [self setAutoupdate:YES];
  312.     [self _setMenuCellsUpdateAction:[NXApp mainMenu]];
  313.  
  314.     /* set version number */
  315.     [versionNum setStringValue:versionNUMBER];
  316.  
  317.     /* add supported image file types */
  318.     [PaletteCell addImageClass:[GifImageRep class]        , ".gif"              , (char*)nil];
  319.     [PaletteCell addImageClass:[NXBitmapImageRep class]    , ".tiff", ".icon"    , (char*)nil];
  320.     [PaletteCell addImageClass:[NXEPSImageRep class]    , ".eps", ".ps", ".ai", (char*)nil];
  321.   
  322.     /* center information panel */
  323.     [infoPanel center];
  324.     [helpPanel center];
  325.     [prefPanel center];
  326.  
  327.     /* make app active */
  328.     [NXApp activateSelf:YES];
  329.   
  330.     /* find real appIcon local window number and register for dragging */
  331.     [[NXApp appIcon] setDelegate:self];
  332.     NXConvertWinNumToGlobal([[NXApp appIcon] windowNum], &appIconWinNum);
  333.     NXConvertGlobalToWinNum(appIconWinNum, &appIconWinNum);
  334.     pbsTypes[0] = NXFilenamePboardType;
  335.     [[NXApp appIcon] registerForDraggedTypes:pbsTypes count:1];
  336.  
  337.     return self;
  338. }
  339.  
  340. /* application termination (check windows for unsaved files) */
  341. - appWillTerminate:sender
  342. {
  343.     
  344.     /* display panel if unsaved files are found */
  345.     if ([Portfolio isDocEdited]) {
  346.         int rtn;
  347.         const char *msg, *quit, *qAny, *cncl;
  348.         msg  = NXLocalizedString("There are edited windows.", (char*)nil,(char*)nil);
  349.         quit = NXLocalizedString("Quit", (char*)nil,(char*)nil);
  350.         qAny = NXLocalizedString("Quit Anyway", (char*)nil,(char*)nil);
  351.         cncl = NXLocalizedString("Cancel", (char*)nil,(char*)nil);
  352.         rtn = NXRunAlertPanel(quit, msg, qAny, cncl, (char*)nil);
  353.         if (rtn == NX_ALERTALTERNATE) return (id)nil;
  354.     }
  355.     
  356.     /* MUST unregister appIcon window, otherwise drag may fail next time app is launched */
  357.     [[NXApp appIcon] unregisterDraggedTypes];
  358.     
  359.     /* return */
  360.     return self;
  361. }
  362.  
  363. /* indicate to Workspace Manager that I accept files */
  364. - (BOOL)appAcceptsAnotherFile:sender { return YES; }
  365.  
  366. /* open a Workspace Manager provided file */
  367. - (int)appOpenFile:(char*)filename type:(char*)type
  368. {
  369.     [[Portfolio alloc] initFromFile:filename];
  370.     return YES;
  371. }
  372.  
  373. // -------------------------------------------------------------------------------------
  374. // application icon window delegate
  375. // - This section handles files dragged and dropped onto the application icon
  376. static char        iconFiles[MAXPATHLEN + 1] = { 0 };
  377.  
  378. /* set dock icon to specified image */
  379. - _setDockIcon:image
  380. {
  381.     id                iconWin = [NXApp appIcon];    
  382.     NXPoint            iconOrigin = { 0.0, 0.0 };
  383.     NXSize            imageSize;
  384.     static id        tileImage = (id)nil;
  385.     static NXSize    tileSize = { 0.0, 0.0 };
  386.   
  387.     /* init dock icon tile */
  388.     if (!tileImage && (tileImage = [NXImage findImageNamed:"NXAppTile"])) {
  389.         [tileImage getSize:&tileSize];
  390.     }
  391.  
  392.     /* draw background tile */
  393.     [[iconWin contentView] lockFocus];
  394.     PSsetinstance(FALSE);
  395.     [tileImage composite:NX_COPY toPoint:&iconOrigin];
  396.     [tileImage getSize:&tileSize];
  397.     [image getSize:&imageSize];
  398.     iconOrigin.x = (tileSize.width  - imageSize.width ) / 2.0;
  399.     iconOrigin.y = (tileSize.height - imageSize.height) / 2.0;
  400.     [image composite:NX_SOVER toPoint:&iconOrigin];
  401.     [[iconWin contentView] unlockFocus];
  402.     [iconWin display];
  403.   
  404.     return self;
  405. }
  406.  
  407. /* files entered icon window */
  408. // - save the list of file names and the representing icon image
  409. - (NXDragOperation)draggingEntered:sender
  410. {
  411.     char        *fileList;
  412.     int            fileListLen;
  413.     Pasteboard    *pb = [sender draggingPasteboard];
  414.     static id    openFolder = (id)nil;
  415.     if (!openFolder) openFolder = [NXImage findImageNamed:"openFolder"];
  416.     if ([pb readType:NXFilenamePboardType data:&fileList length:&fileListLen]) {
  417.         strcpy(iconFiles, fileList);
  418.         [self _setDockIcon:openFolder];
  419.         return NX_DragOperationCopy;
  420.     }
  421.     return NX_DragOperationNone;
  422. }
  423.  
  424. /* mouse exited icon window */
  425. - draggingExited:sender
  426. {
  427.     static id    dockIcon = (id)nil;
  428.     if (!dockIcon) dockIcon = [NXImage findImageNamed:"app"];
  429.     [self _setDockIcon:dockIcon];
  430.     return self;
  431. }
  432.  
  433. /* indicate we accept dragging */
  434. - (BOOL)prepareForDragOperation:sender
  435. {
  436.     if (!*iconFiles) return NO;
  437.     return YES;
  438. }
  439.  
  440. /* files dropped in icon window */
  441. - (BOOL)performDragOperation:sender
  442. {
  443.     if (!*iconFiles) return NO;
  444.     [NXApp activateSelf:YES];
  445.     [[Portfolio alloc] initFromFile:iconFiles];
  446.     [self draggingExited:(id)nil];
  447.     return YES;
  448. }
  449.  
  450. /* find window for number (special case for appIcon window) */
  451. - findWindow:(int)windowNum
  452. {
  453.     return (windowNum == appIconWinNum)? [NXApp appIcon] : [super findWindow:windowNum];
  454. }
  455.  
  456. /*
  457. - (int)dragEnter:(int)windowNum x:(double)x y:(double)y iconOffsetX:(double)hx iconOffsetY:(double)hy iconWindow:(int)iconWindowNum iconX:(double)iconX iconY:(double)iconY iconWidth:(double)iconWidth iconHeight:(double)iconHeight sequenceNumber:(int)seqNum pasteboardName:(char *)pbName operationMask:(int)opMask operation:(int *)op
  458. {
  459.     int gWin;
  460.     NXConvertGlobalToWinNum(windowNum, &gWin);
  461.     printf("dragEnter...(%d/%d)(%d/%d)\n", windowNum, gWin,
  462.         appIconWinNum, [[NXApp appIcon] windowNum]);
  463.     return (int)[super dragEnter:windowNum x:x y:y iconOffsetX:hx iconOffsetY:hy iconWindow:iconWindowNum iconX:iconX iconY:iconY iconWidth:iconWidth iconHeight:iconHeight sequenceNumber:seqNum pasteboardName:pbName operationMask:opMask operation:op];
  464. }
  465. */
  466.  
  467. @end
  468.